/*
 * Copyright (C) 2021 Baidu, Inc. All Rights Reserved.
 */
package com.chukun.rpc.consumer;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

import com.chukun.rpc.core.TinyRpcFuture;
import com.chukun.rpc.core.TinyRpcRequest;
import com.chukun.rpc.core.TinyRpcRequestHolder;
import com.chukun.rpc.core.TinyRpcResponse;
import com.chukun.rpc.protocol.protocol.MessageHeader;
import com.chukun.rpc.protocol.protocol.MessageStatus;
import com.chukun.rpc.protocol.protocol.MessageType;
import com.chukun.rpc.protocol.protocol.ProtocolConstants;
import com.chukun.rpc.protocol.protocol.TinyRpcProtocol;
import com.chukun.rpc.protocol.serialization.SerializationTypeEnum;
import com.chukun.rpc.registry.RegistryService;

import io.netty.channel.DefaultEventLoop;
import io.netty.util.concurrent.DefaultPromise;

/**
 * <p>rpc框架服务代理类<p/>
 *
 * @author chukun
 * @version 1.0
 * @since 1.0-SNAPSHOT
 */
public class TinyRpcInvokerProxy implements InvocationHandler {

    private final String version;
    private final long timeout;
    private final RegistryService registryService;

    public TinyRpcInvokerProxy(String version, long timeout, RegistryService registryService ) {
        this.registryService = registryService;
        this.timeout = timeout;
        this.version = version;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 创建请求协议体
        TinyRpcProtocol<TinyRpcRequest> protocol = new TinyRpcProtocol<>();
        MessageHeader header = new MessageHeader();
        header.setMagic(ProtocolConstants.MAGIC);
        long requestId = TinyRpcRequestHolder.getRequestIdGen().incrementAndGet();
        header.setRequestId(requestId);
        header.setVersion(ProtocolConstants.VERSION);
        header.setMessageType((byte) MessageType.REQUEST.getType());
        header.setStatus((byte) MessageStatus.SUCCESS.getCode());
        header.setSerialization((byte) SerializationTypeEnum.HESSIAN.getType());


        protocol.setHeader(header);

        TinyRpcRequest request = new TinyRpcRequest();
        request.setVersion(this.version);
        request.setClassName(method.getDeclaringClass().getName());
        request.setMethodName(method.getName());
        request.setParams(args);
        request.setParameterTypes(method.getParameterTypes());
        protocol.setBody(request);

        // 创建TinyRpcConsumer
        TinyRpcConsumer consumer = new TinyRpcConsumer();
        TinyRpcFuture<TinyRpcResponse> future = new TinyRpcFuture<>(new DefaultPromise<>(new DefaultEventLoop()), timeout);
        TinyRpcRequestHolder.REQUEST_MAP.put(requestId, future);
        // 发送请求
        consumer.sendRequest(protocol, this.registryService);
        // 获取请求的响应数据
        return future.getPromise().get(future.getTimeout(), TimeUnit.MILLISECONDS).getData();
    }
}
